`timescale 1ns / 1ps
//接收模块-zxd
module MCP_RECIEVE
(
    input             iClk,              //100MHz
    input             iRst_n,
	input             i_miso      ,                                                                		   
    output wire       o_sck       ,                      
    output wire       o_mosi      ,                      
    output wire       o_ssn       ,
    input  [1:0]      ivSend_Choose,     //0:等待 1：发送 2：接收
    output reg        oSend_En, //send enable ok,0:不能发送，1：可发送
	output reg        oreceive_done,     //high pulse
    output wire[7:0]  state,
	output reg [63:0] o_can_data,
	output reg [3:0] rvDataLen,
	output reg [31:0]rvID_rec
);


parameter SEND_ID={8'haa,8'h08,8'hbb,8'hcc};         //send can id
localparam S0  = 8'd0;
localparam S1  = 8'd1;
localparam S2  = 8'd2;
localparam S3  = 8'd3;
localparam S4  = 8'd4;
localparam S5  = 8'd5;
localparam S6  = 8'd6;
localparam S7  = 8'd7;
localparam S8  = 8'd8;
localparam S9  = 8'd9;
localparam S10 = 8'd10;
localparam S11 = 8'd11;
localparam S12 = 8'd12;
localparam S13 = 8'd13;
localparam S14 = 8'd14;
localparam S15 = 8'd15;
localparam S16 = 8'd16;
localparam S17 = 8'd17;
localparam S18 = 8'd18;
localparam S19 = 8'd19;

reg [1:0]  rvSide1;
reg [7:0] rvState_c;
reg [7:0] rvState_n;
reg [7:0] rvData_Tx0;

wire[7:0] wvData_Read;
reg        rWrite_En;   //high level
reg        rRead_En;   //high level
reg  [23:0]rvCmd_write;   //命令+地址+数据 写
reg  [15:0]rvCmd_read;   //命令+地址 读
reg [15:0] rvCnt1;
assign  state=rvState_c;
//1段状态机
always@(posedge iClk or negedge iRst_n)begin
    if(!iRst_n)begin
        rvState_c <= S0;
    end
	else if(ivSend_Choose!=2'd2)begin//如果数据处于发送，在S0等待。
        rvState_c <= S0;
    end
    else begin
        rvState_c <= rvState_n;
    end
end

//2段状态机
always @(*) begin 
    case(rvState_c) 
        S0:rvState_n=ivSend_Choose==2'd2 ? S1 : rvState_c;
        S1:begin
           if(!wSpi_Done)
            rvState_n=rvState_c;
           else begin
                 if(rvData_Tx0[0] && !rvData_Tx0[7] && !rvData_Tx0[5])//接收缓冲器0有数据
                    rvState_n=S2;
                else if(rvData_Tx0[7] || rvData_Tx0[5])
					rvState_n=S17;
				else
                    rvState_n=rvState_c;
				end
            end
        S2:rvState_n=wSpi_Done ? S3 :rvState_c;
        S3:rvState_n=wSpi_Done ? S4:rvState_c;
        S4:rvState_n=wSpi_Done ? S5 :rvState_c;
        S5:
			if({rvID_rec[31:24],rvID_rec[15:0]}=={SEND_ID[31:24],SEND_ID[15:0]})
				rvState_n<=S6;
			else if(rvCnt1>=16'd5000 )
			   rvState_n<=S17;
			else
			   rvState_n<=rvState_c;
		
        S6:rvState_n=wSpi_Done  ? S7 :rvState_c;
        S7:rvState_n=wSpi_Done ? S8 :rvState_c;
        S8:rvState_n=wSpi_Done ? S9 :rvState_c;
        S9:rvState_n=wSpi_Done ? S10 :rvState_c;
        S10:rvState_n=wSpi_Done ? S11 :rvState_c;
        S11:rvState_n=wSpi_Done ? S12 :rvState_c;
        S12:rvState_n=wSpi_Done ? S13 :rvState_c;
        S13:rvState_n=wSpi_Done ? S14 :rvState_c;
        S14:rvState_n=wSpi_Done ? S15 :rvState_c;
        S15:rvState_n=wSpi_Done ? S16 :rvState_c;
        S16:rvState_n=wSpi_Done ? S19 :rvState_c;
        S17:rvState_n=rvCnt1>=16'd1000 ? S18 : rvState_c;
        S18:rvState_n=wSpi_Done ? S1 :rvState_c;
		S19:rvState_n=rvCnt1>=16'd1000 ? S0 : rvState_c;
        default :
            rvState_n=S0;
    endcase
end

always @(posedge iClk or negedge iRst_n) 
begin 
  if(!iRst_n)
   begin
    rvCmd_write   <= 24'h020000;
	rvCmd_read   <= 16'h0300;
	rWrite_En   <= 1'b0;
	rRead_En   <= 1'b0;
	oreceive_done     <= 1'b0;
	rvID_rec           <= 32'd0;
    o_can_data       <= 64'd0;
	oSend_En <= 1'd0;
    rvDataLen<=4'd0;
	rvCnt1<=16'd0;
   end   
  else
    begin
	  case(rvState_c)
	    S0://空闲状态
		  begin
		   oreceive_done <= 1'b0;
	       rWrite_En   <= 1'b0;
	       rRead_En   <= 1'b0;
		   oSend_En   <=1'b1;
		   rvCnt1 <=16'd0;
		   rvID_rec<=32'h0;
		   rvDataLen<=4'd0;
		  end
		S1://读中断
		  begin	
			  rvCnt1<=16'd0;
			  oSend_En   <=1'b1;
			  rRead_En <=wSpi_Done ? 1'b0 :1'b1;
			  rvCmd_read <= {8'h03,8'h2c};
              rvData_Tx0<= wSpi_Done ? wvData_Read : rvData_Tx0;
		   end
		S2://接收标准标识符高位
		  begin
			  rRead_En <=wSpi_Done ? 1'b0 :1'b1;
			  rvCmd_read <= {8'h03,8'h61};
              rvID_rec[31:24] <= wSpi_Done ? wvData_Read : rvID_rec[31:24];
		  end
		S3://接收标准标识符低位
		  begin
			  rRead_En <=wSpi_Done ? 1'b0 :1'b1;
			  rvCmd_read <= {8'h03,8'h62};
			  rvID_rec[23:16] <= wSpi_Done ? wvData_Read : rvID_rec[23:16];
		   end
		S4://接收扩展标识符高位
		  begin
			  rRead_En <=wSpi_Done ? 1'b0 :1'b1;
			  rvCmd_read <= {8'h03,8'h63};
              rvID_rec[15:8] <= wSpi_Done ? wvData_Read : rvID_rec[15:8];
		   end
		S5://接收扩展标识符低位
		  begin
			  rRead_En <=wSpi_Done ? 1'b0 :1'b1;
			  rvCmd_read <= {8'h03,8'h64};
              rvID_rec[7:0] <= wSpi_Done ? wvData_Read : rvID_rec[7:0];
			  rvCnt1<=rvCnt1>=16'd5000 ? rvCnt1 :rvCnt1+1;
		   end
		S6://接收数据长度字节
		  begin
			  rvCnt1<=16'd0;
			  rRead_En <=wSpi_Done ? 1'b0 :1'b1;
			  rvCmd_read <= {8'h03,8'h65};
              rvDataLen <= wSpi_Done ? wvData_Read[3:0] : rvDataLen;
		   end
		S7://接收字节1
		  begin
			  rRead_En <=wSpi_Done ? 1'b0 :1'b1;
			  rvCmd_read <= {8'h03,8'h66};
              o_can_data[7:0] <= wSpi_Done ? wvData_Read : o_can_data[7:0];
		   end
		S8://接收字节2
		  begin
			  rRead_En <=wSpi_Done ? 1'b0 :1'b1;
			  rvCmd_read <= {8'h03,8'h67};
              o_can_data[15:8] <= wSpi_Done ? wvData_Read : o_can_data[15:8];
		   end
		S9://接收字节3
		  begin
			  rRead_En <=wSpi_Done ? 1'b0 :1'b1;
			  rvCmd_read <= {8'h03,8'h68};
              o_can_data[23:16] <= wSpi_Done ? wvData_Read : o_can_data[23:16];
		   end
		S10://接收字节4
		  begin
			  rRead_En <=wSpi_Done ? 1'b0 :1'b1;
			  rvCmd_read <= {8'h03,8'h69};
              o_can_data[31:24] <= wSpi_Done ? wvData_Read : o_can_data[31:24];
		   end
		S11://接收字节5
		  begin
			 rRead_En <=wSpi_Done ? 1'b0 :1'b1;
			  rvCmd_read <= {8'h03,8'h6a};
              o_can_data[39:32] <= wSpi_Done ? wvData_Read : o_can_data[39:32];
		   end
		S12://接收字节6
		  begin
			  rRead_En <=wSpi_Done ? 1'b0 :1'b1;
			  rvCmd_read <= {8'h03,8'h6b};
              o_can_data[47:40] <= wSpi_Done ? wvData_Read : o_can_data[47:40];
		   end
		S13://接收字节7
		  begin
			  rRead_En <=wSpi_Done ? 1'b0 :1'b1;
			  rvCmd_read <= {8'h03,8'h6c};
              o_can_data[55:48] <= wSpi_Done ? wvData_Read : o_can_data[55:48];
		   end
		S14://接收字节8
		  begin
			  rRead_En <=wSpi_Done ? 1'b0 :1'b1;
			  rvCmd_read <= {8'h03,8'h6d};
              o_can_data[63:56] <= wSpi_Done ? wvData_Read : o_can_data[63:56];
		   end
		S15://读中断
		  begin
              rvData_Tx0<=8'd0;
			  rRead_En <=wSpi_Done ? 1'b0 :1'b1;
			  rvCmd_read <= {8'h03,8'h2c};
              rvData_Tx0 <= wSpi_Done ? wvData_Read : rvData_Tx0;
		   end
		S16://复位接收中断0
		  begin
			  oSend_En   <=1'b0;
			  rWrite_En <= wSpi_Done ? 1'b0 :1'b1;
              rRead_En <= 0;
			  rvCmd_write <= {8'h02,8'h2c,{rvData_Tx0[7:1],1'b0}};
		   end 
		S17://复位延时
			begin
			  rvCnt1<=rvCnt1>=16'd1000 ? rvCnt1 :rvCnt1+1;
		   end
		S18://复位接收错误中断
			begin
			  rvCnt1<=16'd0;
			  oSend_En   <=1'b0;
			  rWrite_En <= wSpi_Done ? 1'b0 :1'b1;
              rRead_En <= 0;
			  rvCmd_write <= {8'h02,8'h2c,8'h00};
		   end
		S19://接收结束
		  begin
		    rvCnt1<=rvCnt1>=16'd1000 ? rvCnt1 :rvCnt1+1;
			oreceive_done   <=1'b1;
			oSend_En   <=1'b1;
		  end
		default:;
	  endcase
	end
end

//*******************程序调用*******************
SPI 
#  
(   .T(100),		//SPI时钟周期，1MHz
	.Len_WR(24)		//写指令的位数(写入指令+写入地址+写入的数据)
)
u_SPI_Send(
    .iClk        (iClk        ),
    .iRst_n      (iRst_n      ),
    .o_sck       (o_sck       ),
    .o_mosi      (o_mosi      ),
    .i_miso      (i_miso      ),
    .o_ssn       (o_ssn       ),
    .ivCmd_write (rvCmd_write ),
    .ivCmd_read  (rvCmd_read  ),
    .ovData      (wvData_Read      ),
    .iWrite_En   (rWrite_En   ),
    .iRead_En    (rRead_En    ),
    .oSpi_INT    (wSpi_Done    )
);

endmodule
